package thread;

/**
 * 多线程并发安全问题
 * 当多个线程并发操作统一临界资源，由于线程切换实际不确定，导致操作顺序出现混乱从而产生不良后果。
 * 临界资源:操作该资源的完整过程同一时刻只能被单个线程进行
 */
public class SyncDemo {
    private static boolean success1;
    private static boolean success2;
    public static void main(String[] args) {
        Bank bank = new Bank();

        while(true) {
            Thread t1 = new Thread() {
                public void run() {
                    success1 = bank.getMoney(20000);
                }
            };
            Thread t2 = new Thread() {
                public void run() {
                    success2 = bank.getMoney(20000);
                }
            };
            t1.start();
            t2.start();

            try {
                Thread.sleep(10);//让主线程卡主10毫秒
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            if (success1 && success2) {
                System.out.println("BUG卡成功！");
                break;
            } else {
                System.out.println("没成功，存上再试");
                bank.saveAccount(20000);
                success1 = false;
                success2 = false;
            }
        }
    }
}

class Bank{
    private int account = 20000;//某人的账号余额
    public synchronized boolean getMoney(int money){
        int account = getAccount();//查询账号余额
        if(account>=money){//判断账号余额是否足够
            account = account-money;//扣除要取走的钱
            //在这个位置发生线程切换就可能出现并发安全问题
            Thread.yield();//主动让当前线程放弃本次剩余时间片，模拟执行到这里没时间了
            saveAccount(account);//重新记账
            return true;//允许出钞
        }
        return false;//拒绝出钞
    }
    public void saveAccount(int account){
        this.account = account;
    }
    public int getAccount(){
        return account;
    }
}











